package com.it.juxiang.demo.bool;

import com.it.juxiang.demo.bool.dto.LoginRecord;
import org.springframework.stereotype.Component;

import java.util.LinkedList;

/**
 * 用户登录记录限制类
 * 限制在一定时长（thresholdInMillisecond）内最多登录（maxLoginTimes）次
 */
@Component
public class UserLoginLimiter {
    //默认限制器，限制在60秒之内最多访问10次
    private int maxLoginTimes=10; //一定时间（thresholdInMillisecond值）内的最多登录次数
    private int thresholdInMillisecond=60000; //时长
    private LinkedList<LoginRecord> loginRecordList=new LinkedList<LoginRecord>(); //最近的登录队列



    /**
     * 检查登录记录，
     * 对在（thresholdInMillisecond）时长内超过（maxloginTimes）次的登录记录返回false，否则返回true;
     * @param ip
     * @return
     */
    public boolean check(String ip) {

        //检查设置的值，对0及负数表示不限制登录
        if (maxLoginTimes <= 0 || thresholdInMillisecond <= 0) return true;

        LoginRecord loginRecord=new LoginRecord(ip,System.currentTimeMillis());

        //队列长度未到maxLoginTimes的不用限制
        if (loginRecordList.size() < maxLoginTimes) {
            loginRecordList.addLast(loginRecord);
            return true;
        }

        //队列长度达到maxLoginTimes的，清理和当前记录比较超过thresholdInMillisecond值的记录
        LoginRecord firstLR = loginRecordList.getFirst();
        while (loginRecordList.size() > 0 && firstLR.getTime() + thresholdInMillisecond < loginRecord.getTime()) {
            loginRecordList.removeFirst();
            if (loginRecordList.size() > 0) {
                firstLR = loginRecordList.getFirst();
            } else {
                break;
            }
        }

        //检查队列是否有空间添加新的记录
        if (loginRecordList.size() < maxLoginTimes) {
            loginRecordList.addLast(loginRecord);
            return true;
        } else {
            //队列中的记录与当前登录记录发生在thresholdInMillisecond内，拒绝
            return false;
        }
    }

}
